package cn.infrabase.crypto.digest;

import cn.infrabase.core.util.CharsetUtils;
import cn.infrabase.core.util.StringUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.io.InputStream;
import java.nio.charset.Charset;

/**
 * 摘要工具类。
 *
 * @author Weimin Gao
 * @since 1.0.0
 **/
public class DigestUtils {

    // -----------------------------------------------------------------------------------------------------------------
    // md5

    /**
     * 计算32位MD5摘要值。
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static byte[] md5(byte[] data) {
        return new Md5().digest(data);
    }

    /**
     * 计算32位MD5摘要值。
     *
     * @param data    被摘要数据。
     * @param charset 被摘要数据字符集。
     * @return 摘要结果。
     */
    public static byte[] md5(String data, @Nullable String charset) {
        return new Md5().digest(data, CharsetUtils.charset(charset));
    }

    /**
     * 计算32位MD5摘要值。
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static byte[] md5(String data) {
        return new Md5().digest(data, CharsetUtils.CHARSET_UTF_8);
    }

    /**
     * 计算32位MD5摘要值。
     *
     * @param data 被摘要数据流。
     * @return 摘要结果。
     */
    public static byte[] md5(InputStream data) {
        return new Md5().digest(data);
    }

    /**
     * 计算32位MD5摘要值。
     *
     * @param file 被摘要文件。
     * @return 摘要结果。
     */
    public static byte[] md5(File file) {
        return new Md5().digest(file);
    }

    // -----------------------------------------------------------------------------------------------------------------
    // md5Hex

    /**
     * 计算16位MD5摘要值。
     *
     * @param data    被摘要数据。
     * @param charset 被摘要数据字符集。
     * @return 摘要结果。
     */
    public static String md5Hex(String data, @Nullable String charset) {
        return new Md5().digestHex(data, charset);
    }

    /**
     * 计算MD5摘要值。
     *
     * @param data 被摘要数据。
     * @return MD5摘要值。
     */
    public static String md5Hex(String data) {
        return new Md5().digestHex(data, CharsetUtils.UTF_8);
    }

    /**
     * 计算MD5摘要值。
     *
     * @param data 被摘要数据。
     * @return MD5摘要值。
     */
    public static String md5Hex(byte[] data) {
        return new Md5().digestHex(data);
    }

    /**
     * 计算MD5摘要值，返回摘要结果中间第9位到第24位的值。
     *
     * @param data    被摘要数据。
     * @param charset 编码。
     * @return 摘要结果中间第9位到第24位的值。
     */
    public static String md5Hex16(String data, @Nullable Charset charset) {
        return new Md5().digestHex16(data, charset);
    }

    /**
     * 计算MD5摘要值，返回摘要结果中间第9位到第24位的值。
     *
     * @param data 被摘要数据。
     * @return 摘要结果中间第9位到第24位的值。
     */
    public static String md5Hex16(String data) {
        return new Md5().digestHex16(data);
    }

    /**
     * MD5摘要值取16位摘要值。
     *
     * @param md5Hex MD5摘要值。
     * @return 摘要结果中间第9位到第24位的值。
     */
    public static String md5HexTo16(@Nonnull String md5Hex) {
        return md5Hex.substring(8, 24);
    }

    // -----------------------------------------------------------------------------------------------------------------
    // SHA-1

    /**
     * 计算SHA-1摘要值。
     *
     * @param data 被摘要数据。
     * @return SHA-1摘要数据。
     */
    public static byte[] sha1(byte[] data) {
        return new Digester(DigestAlgorithm.SHA1).digest(data);
    }

    /**
     * 计算SHA-1摘要值。
     *
     * @param data    被摘要数据。
     * @param charset 被摘要数据的字符集。
     * @return 摘要结果。
     */
    public static byte[] sha1(String data, @Nullable Charset charset) {
        return new Digester(DigestAlgorithm.SHA1).digest(StringUtils.bytes(data, charset));
    }

    /**
     * 计算SHA-1摘要值。
     *
     * @param data    被摘要数据。
     * @param charset 被摘要数据的字符集。
     * @return 摘要结果。
     */
    public static byte[] sha1(String data, @Nullable String charset) {
        return new Digester(DigestAlgorithm.SHA1).digest(data, CharsetUtils.charset(charset));
    }

    /**
     * 计算SHA-1摘要值。
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static byte[] sha1(String data) {
        return new Digester(DigestAlgorithm.SHA1).digest(data, CharsetUtils.CHARSET_UTF_8);
    }

    /**
     * 计算SHA-1摘要值。
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static byte[] sha1(InputStream data) {
        return new Digester(DigestAlgorithm.SHA1).digest(data);
    }

    /**
     * 计算SHA-1摘要值。
     *
     * @param file 被摘要文件。
     * @return 摘要结果。
     */
    public static byte[] sha1(File file) {
        return new Digester(DigestAlgorithm.SHA1).digest(file);
    }

    /**
     * 计算SHA-1摘要值，并转为16进制字符串。
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static String sha1Hex(byte[] data) {
        return new Digester(DigestAlgorithm.SHA1).digestHex(data);
    }

    /**
     * 计算SHA-1摘要值，并转为16进制字符串。
     *
     * @param data    被摘要数据。
     * @param charset 被摘要数据的字符集。
     * @return 摘要结果。
     */
    public static String sha1Hex(String data, String charset) {
        return new Digester(DigestAlgorithm.SHA1).digestHex(data, charset);
    }

    /**
     * 计算SHA-1摘要值，并转为16进制字符串。
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static String sha1Hex(String data) {
        return new Digester(DigestAlgorithm.SHA1).digestHex(data, CharsetUtils.CHARSET_UTF_8);
    }

    /**
     * 计算SHA-1摘要值，并转为16进制字符串。
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static String sha1Hex(InputStream data) {
        return new Digester(DigestAlgorithm.SHA1).digestHex(data);
    }

    /**
     * 计算SHA-1摘要值，并转为16进制字符串。
     *
     * @param file 被摘要文件。
     * @return 摘要结果。
     */
    public static String sha1Hex(File file) {
        return new Digester(DigestAlgorithm.SHA1).digestHex(file);
    }

    // -----------------------------------------------------------------------------------------------------------------
    // SHA-256

    /**
     * 计算SHA-256摘要值。
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static byte[] sha256(byte[] data) {
        return new Digester(DigestAlgorithm.SHA256).digest(data);
    }

    /**
     * 计算SHA-256摘要值。
     *
     * @param data    被摘要数据。
     * @param charset 被摘要数据字符集。
     * @return 摘要结果。
     */
    public static byte[] sha256(String data, @Nullable String charset) {
        return new Digester(DigestAlgorithm.SHA256).digest(data, charset);
    }

    /**
     * 计算SHA-256摘要值。
     *
     * @param data    被摘要数据。
     * @param charset 被摘要数据字符集。
     * @return 摘要结果。
     */
    public static byte[] sha256(String data, @Nullable Charset charset) {
        return new Digester(DigestAlgorithm.SHA256).digest(data, charset);
    }

    /**
     * 计算SHA-256摘要值。
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static byte[] sha256(String data) {
        return new Digester(DigestAlgorithm.SHA256).digest(data, CharsetUtils.CHARSET_UTF_8);
    }

    /**
     * 计算SHA-256摘要值。
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static byte[] sha256(InputStream data) {
        return new Digester(DigestAlgorithm.SHA256).digest(data);
    }

    /**
     * 计算SHA-256摘要值。
     *
     * @param file 被摘要文件。
     * @return 摘要结果。
     */
    public static byte[] sha256(File file) {
        return new Digester(DigestAlgorithm.SHA256).digest(file);
    }

    /**
     * 计算SHA-256摘要值，并转为16进制字符串
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static String sha256Hex(byte[] data) {
        return new Digester(DigestAlgorithm.SHA256).digestHex(data);
    }

    /**
     * 计算SHA-256摘要值，并转为16进制字符串
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static String sha256Hex(String data, @Nullable String charset) {
        return new Digester(DigestAlgorithm.SHA256).digestHex(data, charset);
    }

    /**
     * 计算SHA-256摘要值，并转为16进制字符串
     *
     * @param data    被摘要数据。
     * @param charset 被摘要数据字符集。
     * @return 摘要结果。
     */
    public static String sha256Hex(String data, @Nullable Charset charset) {
        return new Digester(DigestAlgorithm.SHA256).digestHex(data, charset);
    }

    /**
     * 计算SHA-256摘要值，并转为16进制字符串
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static String sha256Hex(String data) {
        return sha256Hex(data, CharsetUtils.CHARSET_UTF_8);
    }

    /**
     * 计算SHA-256摘要值，并转为16进制字符串
     *
     * @param data 被摘要数据。
     * @return 摘要结果。
     */
    public static String sha256Hex(InputStream data) {
        return new Digester(DigestAlgorithm.SHA256).digestHex(data);
    }

    /**
     * 计算SHA-256摘要值，并转为16进制字符串
     *
     * @param file 被摘要文件。
     * @return 摘要结果。
     */
    public static String sha256Hex(File file) {
        return new Digester(DigestAlgorithm.SHA256).digestHex(file);
    }

}
